package com.liuhung.base.shiro;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

import com.liuhung.ash.security.entity.Permission;
import com.liuhung.ash.security.entity.Role;
import com.liuhung.ash.security.entity.Users;
import com.liuhung.ash.security.service.PermissionServiceShiro;
import com.liuhung.ash.security.service.RoleServiceShiro;
import com.liuhung.ash.security.service.UsersServiceShiro;

public class ShiroDbRealm extends AuthorizingRealm {

	private UsersServiceShiro usersServiceShiro ;
	private RoleServiceShiro roleServiceShiro ;
	private PermissionServiceShiro permissionServiceShiro;

	private final static Logger log = Logger.getLogger(ShiroDbRealm.class);

	/**
	 * 验证当前Subject（可理解为当前用户）所拥有的权限，且给其授权。
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(
			PrincipalCollection principals) {
		// 获取当前登录的用户名,等价于(String)principals.fromRealm(this.getName()).iterator().next()
		String currentUsername = (String) super.getAvailablePrincipal(principals);
		List<String> roleList = new ArrayList<String>();
		List<String> permissionList = new ArrayList<String>();
		// 从数据库中获取当前登录用户的详细信息
		Users users = usersServiceShiro.findUserByUserName(currentUsername);
		if (users.getRoles() != null && users.getRoles().size() > 0) {
			for (Role role : users.getRoles()) {
				roleList.add(role.getEnname());
				log.info("为用户" + users.getUsername() + "授权" + role.getEnname()
						+ "角色");
			}
		}			
		if (users.getPermissions() != null && users.getPermissions().size() > 0) {
			for (Permission p : users.getPermissions()) {
				permissionList.remove(p.getModel().getEnname()+":"+p.getAction());
				permissionList.add(p.getModel().getEnname()+":"+p.getAction());
				log.info("为用户" + users.getUsername() + "授权" + p.getName()
						+ "权限");
			}
		}
		
		// 为当前用户设置角色和权限
		SimpleAuthorizationInfo simpleAuthorInfo = new SimpleAuthorizationInfo();
		simpleAuthorInfo.addRoles(roleList);

		simpleAuthorInfo.addStringPermissions(permissionList);
		return simpleAuthorInfo;
	}

	/**
	 * 认证回调函数,登录时调用.
	 */
	@SuppressWarnings("unused")
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken authcToken) {
		// 获取基于用户名和密码的令牌
		AuthenticationInfo authcInfo = null;
		UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
		System.out.println("token:"+token.getUsername()+"{"+token.getPassword());
		Users user = usersServiceShiro.findUserByUserName(token.getUsername());
		System.out.println();
		System.out.println("sys:"+user.getUsername()+"___"+user.getPassword());
		if (user == null) {
			throw new UnknownAccountException("用户名<b> " + token.getUsername()+ " </b>不存在，请核查。");// 未知账户
		} else if (user.getStatus() == 0) {
			throw new LockedAccountException("此用户已锁定，请与管理员联系。");// 账户已锁定，与管理员联系
		} else {
			System.out.println(user.getUsername()+"{"+user.getPassword());
			authcInfo = new SimpleAuthenticationInfo(user.getUsername(),
					user.getPassword(), getName());
			this.setSession("currentUser", user);
		}
		return authcInfo;
	}

	/**
	 * 更新授权信息缓存
	 * */
	public void clearCachedAuthorizationInfo(String principal) {
		SimplePrincipalCollection principals = new SimplePrincipalCollection(
				principal, getName());
		clearCachedAuthorizationInfo(principals);
	}

	/**
	 * ShiroSession设置
	 * 
	 * @see 使用时直接用HttpSession.getAttribute(key)就可以取到
	 */
	private void setSession(Object key, Object value) {
		Subject currentUser = SecurityUtils.getSubject();
		if (null != currentUser) {
			Session session = currentUser.getSession();
			if (null != session) {
				session.setAttribute(key, value);
			}
		}
	}
	public UsersServiceShiro getUsersServiceShiro() {
		return usersServiceShiro;
	}

	public void setUsersServiceShiro(UsersServiceShiro usersServiceShiro) {
		this.usersServiceShiro = usersServiceShiro;
	}

	public RoleServiceShiro getRoleServiceShiro() {
		return roleServiceShiro;
	}

	public void setRoleServiceShiro(RoleServiceShiro roleServiceShiro) {
		this.roleServiceShiro = roleServiceShiro;
	}

	public PermissionServiceShiro getPermissionServiceShiro() {
		return permissionServiceShiro;
	}

	public void setPermissionServiceShiro(PermissionServiceShiro permissionServiceShiro) {
		this.permissionServiceShiro = permissionServiceShiro;
	}

	

	

}
